/*
 * Copyright (c) 2015-2016, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef WSNPROTOCOL_H_
#define WSNPROTOCOL_H_

#include "stdint.h"

#include "oad/oad_target.h"

#define WSNPROTOCOL_CONCENTRATOR_ADDRESS     0x00
#define WSNPROTOCOL_EASYLINK_MODULATION     EasyLink_Phy_Custom

#define WSNPROTOCOL_FW_VERSION_STR_LEN                 32

#define WSNPROTOCOL_DEFAULT_MAX_RETRIES 2
#define WSNPROTOCOL_DEFAULT_ACK_TIMEOUT_TIME_MS (10)
#define WSNPROTOCOL_DEFAULT_REQ_TIMEOUT_TIME_MS (10)
#define WSNPROTOCOL_DEFAULT_MSG_PENDING_TIMEOUT_TIME_MS (10)

#define WSNPROTOCOL_OPERATION_NONE_BLOCKING 0
#define WSNPROTOCOL_OPERATION_BLOCKING 1

//Async Packet Types
#define WSNPROTOCOL_PACKET_TYPE_ACK_PACKET              0x00
#define WSNPROTOCOL_PACKET_TYPE_ADC_SENSOR_PACKET       0x01
#define WSNPROTOCOL_PACKET_TYPE_DM_SENSOR_PACKET        0x02
#define WSNPROTOCOL_PACKET_TYPE_OAD_END                 0x03

//Req/Rsp Packet Types
#define WSNPROTOCOL_PACKET_TYPE_REQ_RSP               0x20
#define WSNPROTOCOL_PACKET_TYPE_FW_VERSION_REQ        (WSNPROTOCOL_PACKET_TYPE_REQ_RSP | 0x00)
#define WSNPROTOCOL_PACKET_TYPE_FW_VERSION_RSP        (WSNPROTOCOL_PACKET_TYPE_REQ_RSP | 0x01)
#define WSNPROTOCOL_PACKET_TYPE_OAD_IMG_IDENTIFY_REQ  (WSNPROTOCOL_PACKET_TYPE_REQ_RSP | 0x02)
#define WSNPROTOCOL_PACKET_TYPE_OAD_IMG_IDENTIFY_RSP  (WSNPROTOCOL_PACKET_TYPE_REQ_RSP | 0x03)
#define WSNPROTOCOL_PACKET_TYPE_OAD_BLOCK_REQ         (WSNPROTOCOL_PACKET_TYPE_REQ_RSP | 0x04)
#define WSNPROTOCOL_PACKET_TYPE_OAD_BLOCK_RSP         (WSNPROTOCOL_PACKET_TYPE_REQ_RSP | 0x05)

#define WSNProtocol_isAsync(type) ((type > WSNPROTOCOL_PACKET_TYPE_ACK_PACKET) && (type < WSNPROTOCOL_PACKET_TYPE_REQ_RSP))
#define WSNProtocol_isAck(type) (type == WSNPROTOCOL_PACKET_TYPE_ACK_PACKET)
#define WSNProtocol_isRsp(type) ((type > WSNPROTOCOL_PACKET_TYPE_REQ_RSP) && (type & 0x01))
#define WSNProtocol_isReq(type) ((type >= WSNPROTOCOL_PACKET_TYPE_REQ_RSP) && !(type & 0x01))

#define PKT_TYPE_OFFSET 1

/// Priority of RF commands
typedef enum {
    WSNProtocol_DevType_Concentrator = 0, ///<device is the concentrator of the wsn
    WSNProtocol_DevType_Node = 1,         ///<device is the node of the wsn
} WSNProtocol_DevType;

typedef enum {
    WSNProtocol_Status_Success,
    WSNProtocol_Failed,
    WSNProtocol_FailedNotConnected,
    WSNProtocol_FailedTimeout,
    WSNProtocol_FailedCanceled,
    WSNProtocol_FailedMsgInProgress,
} WSNProtocol_Status_t;

typedef struct {
    uint8_t sourceAddress;
    uint8_t packetType;
} WSNProtocol_PacketHeader_t;

typedef struct {
    WSNProtocol_PacketHeader_t header;
    bool msgPending;
} WSNProtocol_AckPacket_t;

typedef struct  {
    WSNProtocol_PacketHeader_t header;
    uint16_t adcValue;
} WSNProtocol_AdcSensorPacket_t;

typedef struct {
    uint16_t adcValue;
    uint16_t batt;
    uint32_t time100MiliSec;
    uint8_t button;
} WSNProtocol_DmSensorData_t;

typedef struct {
    WSNProtocol_PacketHeader_t header;
    WSNProtocol_DmSensorData_t dmSensorData;
} WSNProtocol_DualModeSensorPacket_t;


typedef struct {
    WSNProtocol_PacketHeader_t header;
    uint8_t status;
} WSNProtocol_OadEndPacket_t;

typedef struct  {
  WSNProtocol_PacketHeader_t header;
} WSNProtocol_FwVersionReqPacket_t;

typedef struct {
    WSNProtocol_PacketHeader_t header;
    char fwVersion[WSNPROTOCOL_FW_VERSION_STR_LEN];
} WSNProtocol_FwVersionRspPacket_t;

typedef struct {
    WSNProtocol_PacketHeader_t header;
    uint8_t imgMetaData[16];
} WSNProtocol_OadImgIdentifyReqPacket_t;

typedef struct {
    WSNProtocol_PacketHeader_t header;
    uint8_t status;
} WSNProtocol_OadImgIdentifyRspPacket_t;

typedef struct {
    WSNProtocol_PacketHeader_t header;
    uint16_t blockNum;
} WSNProtocol_OadBlockReqPacket_t;

typedef struct {
    WSNProtocol_PacketHeader_t header;
    uint8_t block[OAD_BLOCK_SIZE + 2];
} WSNProtocol_OadBlockRspPacket_t;

// Radio Protocol Callbacks
typedef void (*rpDefaultCb_t)(void);
typedef void (*rpAckCb_t)(uint8_t srcAddr);
typedef void (*rpAdcPacketCb_t)(uint8_t srcAddr, int16_t adcData);
typedef void (*rpDmSensorPacketCb_t)(uint8_t srcAddr, WSNProtocol_DmSensorData_t dmSensorData);
typedef void (*rpFwVersionReqCb_t)(uint8_t srcAddr);
typedef void (*rpFwVersionRspCb_t)(uint8_t srcAddr, char *fwVersionStr);
typedef void (*rpOadImgIdentifyReqCb_t)(uint8_t srcAddr, uint8_t *imgMetaData);
typedef void (*rpOadImgIdentifyRspCb_t)(uint8_t srcAddr, uint8_t status);
typedef void (*rpOadBlockReqCb_t)(uint8_t srcAddr, uint16_t blkNum);
typedef void (*rpOadBlockRspCb_t)(uint8_t srcAddr, uint8_t *blkData);
typedef void (*rpMsgErrCb_t)(uint8_t dstAddr, uint8_t expectedRsp, WSNProtocol_Status_t status);
typedef struct
{
    rpAckCb_t               pfnAckCb; //Incomming Ack
    rpAdcPacketCb_t         pfnAdcPacketCb; //Incomming Adc packet
    rpDmSensorPacketCb_t    pfnDmPacketCb; //Incomming Dual Mode Adc Packet
    rpFwVersionReqCb_t      pfnFwVersionReqCb; // Incomming FW Req
    rpFwVersionRspCb_t      pfnFwVersionRspCb; //Incomming FW Version Rsp
    rpOadImgIdentifyReqCb_t pfnOadImgIdentifyReqCb; //Incomming Image Identify Req
    rpOadImgIdentifyRspCb_t pfnOadImgIdentifyRspCb; //Incomming Image Identify Rsp
    rpOadBlockReqCb_t       pfnOadBlockReqCb; //Incomming OAD Block Req
    rpOadBlockRspCb_t       pfnOadBlockRspCb; //Incomming OAD Block Rsp
    rpMsgErrCb_t            pfnMsgErrCb;      //error callback
} WSNProtocol_packetCBs_t;

/// @brief RF parameter struct
/// RF parameters are used with the WSNProtocol_open() and WSNProtocol_Params_init() call.
typedef struct {
    WSNProtocol_DevType  devType;                ///< deType:
                                                 ///      WSNProtocol_DevType_Concentrator
                                                 ///      WSNProtocol_DevType_Node
    uint8_t                  devAddress;         ///< Address of node on wireless Sensor Network
    bool                     sleepy;             ///< flag indicatng if node is Rx or Sleep when idle
    uint32_t                 ackTimeoutMs;        ///< Timeout for ack when sending Async packet
    uint32_t                 rspTimeoutMs;        ///< Timeout for response when sending request
    uint32_t                 msgPendingTimeoutMs; ///< Timeout for Rx when Message pending it in Ack set
    uint32_t                 maxRetires;             ///< The Max retreis for Async (Ack) or Req (Rsp) packets
    WSNProtocol_packetCBs_t *pCallbacks;          ///< Application Callbacks for pressing packets
} WSNProtocol_Params_t;

/**
 *  @brief  Function to initialize the WSNProtocol_Params struct to its defaults
 *
 *  @param  params      An pointer to RF_Params structure for
 *                      initialization
 *
 *  Defaults values are:
 *      devType             = WSNProtocol_DevType_Concentrator
 *      devAddress          = WSNPROTOCOL_CONCENTRATOR_ADDRESS
 *      sleepy              = FASLE
 *      ackTimeoutMs        = WSNPROTOCOL_DEFAULT_ACK_TIMEOUT_TIME_MS
 *      rspTimeoutMs        = WSNPROTOCOL_DEFAULT_REQ_TIMEOUT_TIME_MS
 *      msgPendingTimeoutMs = WSNPROTOCOL_DEFAULT_MSG_PENDING_TIMEOUT_TIME_MS
 *      maxretires          = WSNPROTOCOL_DEFAULT_MAX_RETRIES
 *      pCallbacks          = {0}
 */
extern void WSNProtocol_Params_init(WSNProtocol_Params_t *params);

/* Initializes the Wsn Protocol Task and creates all TI-RTOS objects */
extern void WSNProtocol_init(void);

extern void WSNProtocol_open(WSNProtocol_Params_t *params);
extern WSNProtocol_Status_t WSNProtocol_sendAdcData(uint16_t data);
extern WSNProtocol_Status_t WSNProtocol_sendDmPacket(uint8_t dstAddress, WSNProtocol_DmSensorData_t dmSensorPacket);
extern WSNProtocol_Status_t WSNProtocol_sendFwVersionRsp(uint8_t dstAddr, char *fwVersion);
extern WSNProtocol_Status_t WSNProtocol_sendFwVersionReq(uint8_t dstAddr);
extern WSNProtocol_Status_t WSNProtocol_sendImgIdentifyReq(uint8_t dstAddr, uint8_t *pImgInfoData);
extern WSNProtocol_Status_t WSNProtocol_sendOadIdentifyImgRsp(uint8_t address, uint8_t status);
extern WSNProtocol_Status_t WSNProtocol_sendOadImgBlockReq(uint8_t address, uint16_t blockNum);
extern WSNProtocol_Status_t WSNProtocol_sendOadImgBlockRsp(uint8_t dstAddress, uint8_t *block);
extern WSNProtocol_Status_t WSNProtocol_sendAck(uint8_t address, bool messagePending);

extern int8_t WSNProtocol_getLastRssi(void);
extern bool WSNProtocol_isPending(void);
extern void WSNProtocol_cancelPending(void);

#endif /* WSNPROTOCOL_H_ */
